---
title: SAIF.Business.View.Policy security and authorization
summary: Authorization requirements, AD resource groups, security enforcement points, and data-level access control for policy access.
status: draft
owner: SAIF Claims BOF team
last_reviewed: 2026-08-21
library: SAIF.Business.View.Policy
reference_type: embedded
---

# SAIF.Business.View.Policy security and authorization

This page documents authorization mechanisms implemented or consumed by this library. Authentication
is handled entirely by infrastructure (NTLM/AD) and is not application-level — all code receives a
`WindowsIdentity`/`clsSecurityPrincipal` on the request context. `clsPolicySecurity` is a dedicated,
programmatic (non-attribute-based) authorization class: it derives a `clsUserType` from the supplied
principal and implements a composite check — a global secure-policy/AD-resource gate followed by a
per-user-type ownership/scope rule ([Determine whether the current user may view a policy](operations/determine-policy-access.md)).

## Authorization architecture

Local, programmatic, data-scoped authorization performed by a domain-tier class
(`clsPolicySecurity`), combined with a single AD-resource check delegated to the externally-defined
`clsSecurityPrincipal.IsAuthorized` method. No direct `System.DirectoryServices` usage and no direct
WCF `SecurityService` proxy calls are present in this library — the AD lookup is fully encapsulated
behind `clsSecurityPrincipal`, whose implementation is external to this repository.**

```mermaid
flowchart TD
    Caller[Calling code] --> Construct[Construct clsPolicySecurity from clsSecurityPrincipal + DPI]
    Construct --> Gate{SecurePolicyCode = SAIF and not authorized for SAIFpolicyInfo?}
    Gate -->|Yes| Deny([Access denied])
    Gate -->|No| Validity{Policy valid and non-zero?}
    Validity -->|No| Deny
    Validity -->|Yes| UserType[Select Case UserType.UserType]
    UserType --> Result([hasAccess returned to caller])
```

## AD resource catalog

| Resource name | Purpose | Enforcement point | Source |
| --- | --- | --- | --- |
| `SAIFpolicyInfo` | Gates access to "secure" SAIF-owned policies (`SecurePolicyCode = clsConstants.SAIF`). Any user, regardless of user type, is denied access to a secure policy unless this AD resource membership check succeeds. This is a data-level, policy-scoped override that runs before the per-user-type switch. | `clsPolicySecurity.IsPolicyValidForUser(inPolicyData As clsPolicyData)`, via `SecurityPrincipal.IsAuthorized("SAIFpolicyInfo")` | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |

Only one AD resource name is referenced in this library's source. The environment suffix
(`Resource`/`TestResource`) and the underlying AD lookup/domain routing are applied inside
`clsSecurityPrincipal.IsAuthorized`, implemented in the external `SAIF.BOF.Framework.Security`
assembly and not available as source in this repository.*

## Authorization enforcement points

No `[SAIFAuthorize]`/`[SaifAuthorize]` MVC attributes or other attribute-based enforcement points
were found in this library — it is a business/domain-tier VB.NET class library, not an MVC front
end, so attribute-based authorization is not expected here.*

### Programmatic authorization checks

| Class | Method | Resource / Role | Check type | Source |
| --- | --- | --- | --- | --- |
| `clsPolicySecurity` | `IsPolicyValidForUser` | `SAIFpolicyInfo` (secure-policy gate) | `IsAuthorized` | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `IsPolicyValidForUser` | Policy validity gate (`IsValid`/`PolicyNum <> 0`) | Data validity check | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `IsPolicyValidForUser` (Agent case) | Agent/agency number match | Ownership check | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `IsPolicyValidForParentPolicy` | Policyholder/parent-affiliate ownership | Ownership + affiliation-association check | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `IsInGroup` | Group membership | Stored-procedure check ([SQL-VP-033](sql/SQL-033-isingroup.md)) | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `CanSafetyConsultantAccessPolicy` | Loss-control team-assignment match | Username-prefix match | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsPolicySecurity` | `CanAuditorAccessPolicy` | Fee-auditor vendor/audit-record match | SQL query ([SQL-VP-037](sql/SQL-037-canauditoraccesspolicy.md)) | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |

Eight distinct programmatic enforcement points in total (the secure-policy gate + validity gate +
six per-user-type/ownership checks including the internal-user-types unconditional grant). Any user
type not matched by the `Select Case` falls through to an implicit deny (`hasAccess` remains
`False`).*

## Data-level authorization

| Entity type | Validation method | Mechanism | Source |
| --- | --- | --- | --- |
| Policy (secure-policy override) | `clsPolicySecurity.IsPolicyValidForUser` | Composite: `SecurePolicyCode = clsConstants.SAIF` AND not authorized for `SAIFpolicyInfo` → deny | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| Policy (agent) | `clsPolicySecurity.IsPolicyValidForUser` (Agent case) | String match of `UserType.UserNumber` against `inPolicyData.AgentNum` or `inPolicyData.Agency.AgencySeqNum` | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| Policy (policyholder/parent affiliate) | `clsPolicySecurity.IsPolicyValidForParentPolicy` | Self-match on policy number, else lookup of parent association types on the user's own policy data and a match against the requested policy's associations | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| Policy (group) | `clsPolicySecurity.IsInGroup` | Stored procedure `cp_policy_in_group`, parameterized by `GroupID`/`GroupChapterID` ([SQL-VP-033](sql/SQL-033-isingroup.md)) | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| Policy (loss-control consultant) | `clsPolicySecurity.CanSafetyConsultantAccessPolicy` | Team-assignment lookup plus case-insensitive username-prefix match; uses `UserIdName` instead of `UserName` for demo loss-control users | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| Policy (fee auditor/vendor) | `clsPolicySecurity.CanAuditorAccessPolicy` | Direct SQL join across `PA_AUDIT`, `PA_AUDITOR`, `PA_POLICY_PERIOD` filtering on vendor number and policy number, excluding cancelled/completed audits older than a threshold date ([SQL-VP-037](sql/SQL-037-canauditoraccesspolicy.md)) | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |

### Demo-user data masking (privacy control)

`clsPolicyData` exposes `IsDemoUser` (true for any `Demo*` `UserAccessLevel`). When true, the
following properties substitute masked/constant values instead of returning real policyholder data.
This does not gate access — access is governed entirely by `IsPolicyValidForUser` — it only ensures
that once access is granted to a recognized demo-tier user, real PII is not disclosed.*

| Property | Masked value when `IsDemoUser` | Real value otherwise |
| --- | --- | --- |
| Legal name | `clsConstants.DataMaskingConstants.POLICYHOLDER_LEGAL_NAME` | `m_LegalName` |
| Policy name | `clsConstants.DataMaskingConstants.POLICYHOLDER_NAME` | `m_PolicyName` |
| Group name | `clsConstants.DataMaskingConstants.GROUP_NAME` | `m_GroupName` |
| FEID number | `clsConstants.DataMaskingConstants.POLICYHOLDER_FEID` | `m_FeidNum` |
| NCCI risk ID | `clsConstants.DataMaskingConstants.NCCI_RISK_ID` | `m_NcciRiskID` |
| NCCI binder number | Literal `"999999999999999999"` | `m_NcciBinderNum` |
| WCD number | Literal `9999999` | `m_WcdNum` |
| Web address | Literal `"Web Address"` | `m_WebAddr` |

Related demo-user masking also applies to `clsAgency` ([BR-VP-010](business-rules.md#br-vp-010-demo-user-agency-agent-data-masking)),
`clsPolicyAddress` ([BR-VP-011](business-rules.md#br-vp-011-demo-user-address-contact-data-masking)),
and `clsTeamAssignment` ([BR-VP-012](business-rules.md#br-vp-012-team-assignment-masking-preserves-real-username-for-authorization)).

## Segregation of duties

No segregation-of-duties classes, methods, or privilege-combination queries were found in this
library. No `*SegregationOfDuties*`/`*SOD*` naming or queries against `employee_access`/
`menu_structure`-style tables were found.

## Security interfaces and contracts

| Interface / Class | Role | Consumers | Source |
| --- | --- | --- | --- |
| `clsSecurityPrincipal` | Authenticated-identity/principal type exposing `IsAuthorized(ResourceName)`; not defined in this library — consumed from the external `SAIF.BOF.Framework.Security` assembly.** | `clsPolicySecurity` (constructor parameter) | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |
| `clsUserType` | Classifies the authenticated principal into `UserTypes.{SaifEmployee, Agent, PolicyHolder, Group, LossControl, Auditor, MCO, MedProv, Bookkeeper}`; not defined in this library.** | `clsPolicySecurity` | `SAIF.Business.View.Policy\clsPolicySecurity.vb` |

## Inherited security

No inherited authentication/authorization mechanism was returned from the dependency documentation
lookup for this library's `frameworkDensity` base classes (`clsBusinessBase`,
`clsBusinessCollection`, `clsBusinessCollectionBase`, `clsAddress` — all from `saif.framework.core`)
— only generic BOF lifecycle mechanisms with no security-specific content were found, so this
section is omitted.

## Notes
- Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
- Statements marked with `**` could not be confirmed; treat as unknown until verified.
- AD resource names listed here use base names only. The framework appends `Resource` (production) or `TestResource` (non-production) at runtime.
- No WCF `SecurityService` proxy calls, `System.DirectoryServices` usage, or machine/service-account authorization logic were found anywhere in this library.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts. Statements marked with `**` could not be confirmed; treat
> as unknown until verified.

## Sources
- `SAIF.Business.View.Policy\clsPolicySecurity.vb`
- `SAIF.Business.View.Policy\clsPolicyData.vb`
- `SAIF.Business.View.Policy\SAIF.Business.View.Policy.vbproj`
